From 6b14c83b48776eb6a862e26c90e13c0762f71927 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Mon, 5 Sep 2005 19:53:44 +0000 Subject: [PATCH] Fix PCI iomem resource fixup. Signed-off-by: Keir Fraser --- .../arch/xen/i386/kernel/setup.c | 68 +++++++++++++++++- .../arch/xen/x86_64/kernel/e820.c | 71 +++++++++++++++++-- xen/arch/x86/dom0_ops.c | 24 ++++++- xen/common/domain.c | 5 +- xen/common/memory.c | 2 +- xen/include/public/dom0_ops.h | 13 ++++ 6 files changed, 168 insertions(+), 15 deletions(-) diff --git a/linux-2.6-xen-sparse/arch/xen/i386/kernel/setup.c b/linux-2.6-xen-sparse/arch/xen/i386/kernel/setup.c index 1cbe2bb77e..611cd67695 100644 --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/setup.c +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/setup.c @@ -1235,10 +1235,64 @@ static void __init legacy_init_iomem_resources(struct resource *code_resource, struct resource *data_resource) { int i; +#ifdef CONFIG_XEN + dom0_op_t op; + struct dom0_memory_map_entry *map; + unsigned long gapstart, gapsize; + unsigned long long last; +#endif #ifdef CONFIG_XEN_PRIVILEGED_GUEST probe_roms(); #endif + +#ifdef CONFIG_XEN + map = alloc_bootmem_low_pages(PAGE_SIZE); + op.cmd = DOM0_PHYSICAL_MEMORY_MAP; + op.u.physical_memory_map.memory_map = map; + op.u.physical_memory_map.max_map_entries = + PAGE_SIZE / sizeof(struct dom0_memory_map_entry); + BUG_ON(HYPERVISOR_dom0_op(&op)); + + last = 0x100000000ULL; + gapstart = 0x10000000; + gapsize = 0x400000; + + for (i = op.u.physical_memory_map.nr_map_entries - 1; i >= 0; i--) { + struct resource *res; + + if ((last > map[i].end) && ((last - map[i].end) > gapsize)) { + gapsize = last - map[i].end; + gapstart = map[i].end; + } + if (map[i].start < last) + last = map[i].start; + + if (map[i].end > 0x100000000ULL) + continue; + res = alloc_bootmem_low(sizeof(struct resource)); + res->name = map[i].is_ram ? "System RAM" : "reserved"; + res->start = map[i].start; + res->end = map[i].end - 1; + res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; + request_resource(&iomem_resource, res); + } + + free_bootmem(__pa(map), PAGE_SIZE); + + /* + * Start allocating dynamic PCI memory a bit into the gap, + * aligned up to the nearest megabyte. + * + * Question: should we try to pad it up a bit (do something + * like " + (gapsize >> 3)" in there too?). We now have the + * technology. + */ + pci_mem_start = (gapstart + 0xfffff) & ~0xfffff; + + printk("Allocating PCI resources starting at %08lx (gap: %08lx:%08lx)\n", + pci_mem_start, gapstart, gapsize); +#else for (i = 0; i < e820.nr_map; i++) { struct resource *res; if (e820.map[i].addr + e820.map[i].size > 0x100000000ULL) @@ -1264,6 +1318,7 @@ legacy_init_iomem_resources(struct resource *code_resource, struct resource *dat request_resource(res, data_resource); } } +#endif } /* @@ -1271,23 +1326,29 @@ legacy_init_iomem_resources(struct resource *code_resource, struct resource *dat */ static void __init register_memory(void) { +#ifndef CONFIG_XEN unsigned long gapstart, gapsize; unsigned long long last; +#endif int i; + /* Nothing to do if not running in dom0. */ + if (!(xen_start_info->flags & SIF_INITDOMAIN)) + return; + if (efi_enabled) efi_initialize_iomem_resources(&code_resource, &data_resource); else legacy_init_iomem_resources(&code_resource, &data_resource); - if (xen_start_info->flags & SIF_INITDOMAIN) - /* EFI systems may still have VGA */ - request_resource(&iomem_resource, &video_ram_resource); + /* EFI systems may still have VGA */ + request_resource(&iomem_resource, &video_ram_resource); /* request I/O space for devices used on all i[345]86 PCs */ for (i = 0; i < STANDARD_IO_RESOURCES; i++) request_resource(&ioport_resource, &standard_io_resources[i]); +#ifndef CONFIG_XEN /* * Search for the bigest gap in the low 32 bits of the e820 * memory space. @@ -1328,6 +1389,7 @@ static void __init register_memory(void) printk("Allocating PCI resources starting at %08lx (gap: %08lx:%08lx)\n", pci_mem_start, gapstart, gapsize); +#endif } /* Use inline assembly to define this because the nops are defined diff --git a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/e820.c b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/e820.c index 8ca939aef1..c891371b28 100644 --- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/e820.c +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/e820.c @@ -517,11 +517,10 @@ void __init setup_memory_region(void) } #else /* CONFIX_XEN */ + extern unsigned long xen_override_max_pfn; extern union xen_start_info_union xen_start_info_union; -/* - * Guest physical starts from 0. - */ + unsigned long __init e820_end_of_ram(void) { unsigned long max_end_pfn = xen_start_info->nr_pages; @@ -532,11 +531,69 @@ unsigned long __init e820_end_of_ram(void) return xen_override_max_pfn; } - - void __init e820_reserve_resources(void) { - return; /* Xen won't have reserved entries */ + dom0_op_t op; + struct dom0_memory_map_entry *map; + unsigned long gapstart, gapsize, last; + int i, found = 0; + + if (!(xen_start_info->flags & SIF_INITDOMAIN)) + return; + + map = alloc_bootmem_low_pages(PAGE_SIZE); + op.cmd = DOM0_PHYSICAL_MEMORY_MAP; + op.u.physical_memory_map.memory_map = map; + op.u.physical_memory_map.max_map_entries = + PAGE_SIZE / sizeof(struct dom0_memory_map_entry); + BUG_ON(HYPERVISOR_dom0_op(&op)); + + last = 0x100000000ULL; + gapstart = 0x10000000; + gapsize = 0x400000; + + for (i = op.u.physical_memory_map.nr_map_entries - 1; i >= 0; i--) { + struct resource *res; + + if ((last > map[i].end) && ((last - map[i].end) > gapsize)) { + gapsize = last - map[i].end; + gapstart = map[i].end; + found = 1; + } + if (map[i].start < last) + last = map[i].start; + + if (map[i].end > 0x100000000ULL) + continue; + res = alloc_bootmem_low(sizeof(struct resource)); + res->name = map[i].is_ram ? "System RAM" : "reserved"; + res->start = map[i].start; + res->end = map[i].end - 1; + res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; + request_resource(&iomem_resource, res); + } + + free_bootmem(__pa(map), PAGE_SIZE); + + if (!found) { + HYPERVISOR_memory_op(XENMEM_maximum_ram_page, &gapstart); + gapstart = (gapstart << PAGE_SHIFT) + 1024*1024; + printk(KERN_ERR "PCI: Warning: Cannot find a gap in the 32bit address range\n" + KERN_ERR "PCI: Unassigned devices with 32bit resource registers may break!\n"); + } + + /* + * Start allocating dynamic PCI memory a bit into the gap, + * aligned up to the nearest megabyte. + * + * Question: should we try to pad it up a bit (do something + * like " + (gapsize >> 3)" in there too?). We now have the + * technology. + */ + pci_mem_start = (gapstart + 0xfffff) & ~0xfffff; + + printk(KERN_INFO "Allocating PCI resources starting at %lx (gap: %lx:%lx)\n", + pci_mem_start, gapstart, gapsize); } #endif @@ -558,6 +615,7 @@ unsigned long pci_mem_start = 0xaeedbabe; */ __init void e820_setup_gap(void) { +#ifndef CONFIG_XEN unsigned long gapstart, gapsize; unsigned long last; int i; @@ -606,4 +664,5 @@ __init void e820_setup_gap(void) printk(KERN_INFO "Allocating PCI resources starting at %lx (gap: %lx:%lx)\n", pci_mem_start, gapstart, gapsize); +#endif } diff --git a/xen/arch/x86/dom0_ops.c b/xen/arch/x86/dom0_ops.c index 01ea09b74e..06562059c4 100644 --- a/xen/arch/x86/dom0_ops.c +++ b/xen/arch/x86/dom0_ops.c @@ -389,9 +389,31 @@ long arch_do_dom0_op(dom0_op_t *op, dom0_op_t *u_dom0_op) } break; + case DOM0_PHYSICAL_MEMORY_MAP: + { + struct dom0_memory_map_entry entry; + int i; + + for ( i = 0; i < e820.nr_map; i++ ) + { + if ( i >= op->u.physical_memory_map.max_map_entries ) + break; + entry.start = e820.map[i].addr; + entry.end = e820.map[i].addr + e820.map[i].size; + entry.is_ram = (e820.map[i].type == E820_RAM); + (void)copy_to_user( + &op->u.physical_memory_map.memory_map[i], + &entry, sizeof(entry)); + } + + op->u.physical_memory_map.nr_map_entries = i; + (void)copy_to_user(u_dom0_op, op, sizeof(*op)); + } + break; + default: ret = -ENOSYS; - + break; } return ret; diff --git a/xen/common/domain.c b/xen/common/domain.c index a5460759d6..eaea4bcc9d 100644 --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -176,10 +176,7 @@ __initcall(domain_shutdown_finaliser_init); void domain_shutdown(u8 reason) { struct domain *d = current->domain; - struct vcpu *v; - - if(reason == SHUTDOWN_crash) - printk("Domain %d crash detected.\n", d->domain_id); + struct vcpu *v; if ( d->domain_id == 0 ) { diff --git a/xen/common/memory.c b/xen/common/memory.c index c1019c9dba..ca394edb81 100644 --- a/xen/common/memory.c +++ b/xen/common/memory.c @@ -190,7 +190,7 @@ long do_memory_op(int cmd, void *arg) case XENMEM_maximum_ram_page: if ( put_user(max_page, (unsigned long *)arg) ) return -EFAULT; - rc = -ENOSYS; + rc = 0; break; default: diff --git a/xen/include/public/dom0_ops.h b/xen/include/public/dom0_ops.h index b8928b0f68..508ba6779a 100644 --- a/xen/include/public/dom0_ops.h +++ b/xen/include/public/dom0_ops.h @@ -374,6 +374,18 @@ typedef struct { int quirk_id; } dom0_platform_quirk_t; +#define DOM0_PHYSICAL_MEMORY_MAP 40 +typedef struct { + /* IN variables. */ + int max_map_entries; + /* OUT variables. */ + int nr_map_entries; + struct dom0_memory_map_entry { + u64 start, end; + int is_ram; + } *memory_map; +} dom0_physical_memory_map_t; + typedef struct { u32 cmd; u32 interface_version; /* DOM0_INTERFACE_VERSION */ @@ -408,6 +420,7 @@ typedef struct { dom0_getvcpucontext_t getvcpucontext; dom0_getdomaininfolist_t getdomaininfolist; dom0_platform_quirk_t platform_quirk; + dom0_physical_memory_map_t physical_memory_map; } u; } dom0_op_t; -- 2.30.2